"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 故障&可靠性测试
Case Name   : 磁盘满时修改数据库
Create At   : 2021/01/14
@zou_jialiang0505328126
Description :
    1.创建数据库
    2.创建普通用户
    3.使用CFE注入磁盘满故障
    4.修改数据库
    5.清除故障
    6.使用普通用户连接3个数据库，重复执行以下语句3次
    7.修改数据库
    8.使用普通用户连接3个数据库，重复执行以下语句3次
Expect      :
    1.创建成功
    2.创建成功
    3.注入故障成功
    4.修改数据库成功
    5.清除故障成功
    6.连接成功无报错
    7.修改成功
    8.连接到第三个报错
History     :
    modified at 2021-2-5;by @peilinqian;修改建库语句，以防因其他用例异常导致已存在创建库的情况
    Modified by @wan005 2021/3/17: 清除故障后需重启数据库
    Modified by @wan005 2021/8/4: 优化故障后验证断言
    Modified by @wan005 2021/9/6: 删除明文密码
    Modified by @wan005 2021/11/12: 增加stop数据库
"""

import unittest
import time
from yat.test import macro
from yat.test import Node
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread


class Ddldatabase(unittest.TestCase):
    commonshpri = CommonSH('PrimaryDbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('-Opengauss_Reliability_Db_System_Case235.py 开始执行--')
        self.db_primary_db_user = Node(node='PrimaryDbUser')
        self.db_primary_root_node = Node(node='PrimaryRoot')
        self.constant = Constant()
        self.common = Common('PrimaryRoot')
        self.db_disk_name = ''
        self.dbname = 'test_db'
        self.username = 'user_db'
        self.password = macro.PASSWD_INITIAL

    def test_basebackup(self):
        self.log.info('-------------------1.创建数据库-----------------')
        create_db_sql = f'drop database if exists {self.dbname};' \
            f'create database {self.dbname}'
        result = self.commonshpri.executDbSql(create_db_sql)
        self.log.info(result)
        self.assertIn(self.constant.CREATE_DATABASE_SUCCESS_MSG, result)


        self.log.info('------2.创建普通用户-------')
        create_user_sql = f"drop user if exists {self.username};" \
            f"create user {self.username} with password '{self.password}'"
        result = self.commonshpri.executDbSql(create_user_sql)
        self.log.info(result)
        self.assertIn(self.constant.CREATE_ROLE, result)

        self.log.info('---------3.使用CFE注入磁盘满故障---------')
        self.log.info('====================获取主节点磁盘名=============')
        cmd = f"df -h {macro.DB_INSTANCE_PATH}"
        self.log.info(cmd)
        msg = self.db_primary_root_node.sh(cmd).result()
        self.log.info(msg)
        self.db_disk_name = msg.splitlines()[-1].split()[0].strip()

        cfedisk_cmd = f'{macro.CFE_PATH}/cfe  ' \
            f'"inject  rfile_full (diskname)  values  ({self.db_disk_name})"'
        result = self.db_primary_root_node.sh(cfedisk_cmd).result()
        self.log.info(result)

        self.log.info('-------------------4.修改数据库-----------------')
        result = self.commonshpri.executDbSql(
            f'ALTER DATABASE {self.dbname} with CONNECTION LIMIT 2;')
        self.log.info(result)
        self.assertTrue(self.constant.DISK_FULL_MSG in result
                        or self.constant.FAILED_CONNECT_DB in result)

        self.log.info('----------------------5.清除故障----------------------')
        cfedisk_cmd = f'''{macro.CFE_PATH}/cfe "clean  
        rfile_full  where(diskname={self.db_disk_name})"'''
        tmp = self.db_primary_root_node.sh(cfedisk_cmd).result()
        self.log.info(tmp)

        self.log.info('--------重启数据库---------')
        result = self.commonshpri.stopDbCluster()
        self.log.info(result)
        result = self.commonshpri.startDbCluster()
        self.log.info(result)

        self.log.info('---- 6.使用普通用户连接3个数据库，重复执行以下语句3次---')
        connect_thread = []
        for i in range(3):
            connect_thread.append(ComThread(
                self.commonshpri.executDbSql, args=(
                'select pg_sleep(120);', self.dbname,
                f'-U {self.username} -W {self.password}')))
            connect_thread[i].setDaemon(True)
            connect_thread[i].start()
            time.sleep(5)
        for i in range(3):
            connect_thread[i].join(400)
            result = connect_thread[i].get_result()
            self.log.info(result)
            self.assertNotIn('too many', result)
        time.sleep(5)

        self.log.info('-------------------8.修改数据库-----------------')
        result = self.commonshpri.executDbSql(
            f'ALTER DATABASE {self.dbname} with CONNECTION LIMIT 2;')
        self.log.info(result)
        self.assertIn('ALTER', result)

        self.log.info('---- 6.使用普通用户连接3个数据库，重复执行以下语句3次---')
        connect_thread = []
        for i in range(3):
            connect_thread.append(ComThread(
                self.commonshpri.executDbSql, args=(
                'select pg_sleep(120);', self.dbname,
                f'-U {self.username} -W {self.password}')))
            connect_thread[i].setDaemon(True)
            connect_thread[i].start()
            time.sleep(5)
        for i in range(3):
            connect_thread[i].join(400)
            result = connect_thread[i].get_result()
            self.log.info(result)
            if 2 == i:
                self.assertIn('too many', result)
            else:
                self.assertNotIn('too many', result)
        time.sleep(5)

    def tearDown(self):
        self.log.info('-------------------------环境清理------------------------')
        self.log.info('-----------------清除故障----------------------')
        cfedisk_cmd = f'''{macro.CFE_PATH}/cfe "clean  
        rfile_full  where(diskname={self.db_disk_name})"'''
        tmp = self.db_primary_root_node.sh(cfedisk_cmd).result()
        self.log.info(tmp)

        self.log.info('-------------------删除数据库-----------------')
        result = self.commonshpri.executDbSql(
            f'drop database if exists {self.dbname};')
        self.log.info(result)

        self.log.info('----------删除用户----------')
        result = self.commonshpri.executDbSql(
            f"drop user if exists {self.username};")
        self.log.info(result)
        self.log.info('-Opengauss_Reliability_Db_System_Case235.py 执行结束--')
